using System;
using UnityEngine;

namespace ZFramework.Runtime
{
    public partial class ObjectPoolMgr
    {
        public sealed class InternalObject<T> : IReference where T : ObjectBase
        {
            private T _object;
            private int _spawnCount;

            public void Clear()
            {
                _object = null;
                _spawnCount = 0;
            }

            public string Name
            {
                get => _object.Name;
            }

            public int SpawnCount
            {
                get => _spawnCount;
            }
            
            /// <summary>
            /// 获取对象的优先级。
            /// </summary>
            public int Priority
            {
                get
                {
                    return _object.Priority;
                }
                internal set
                {
                    _object.Priority = value;
                }
            }
            
            /// <summary>
            /// 获取对象上次使用时间。
            /// </summary>
            public DateTime LastUseTime
            {
                get
                {
                    return _object.LastUseTime;
                }
            }
            
            /// <summary>
            /// 获取对象是否被加锁。
            /// </summary>
            public bool Locked
            {
                get
                {
                    return _object.Locked;
                }
                internal set
                {
                    _object.Locked = value;
                }
            }
            
            public static InternalObject<T> Create(T obj, bool spawned)
            {
                if (obj == null)
                    return null;
                InternalObject<T> internalObject = ReferencePool.Acquire<InternalObject<T>>();
                internalObject._object = obj;
                internalObject._spawnCount = spawned ? 1 : 0;
                if (spawned)
                {
                    obj.OnSpawn();
                }

                return internalObject;
            }

            public T Peek()
            {
                return _object;
            }

            public T Spawn()
            {
                _spawnCount++;
                _object.LastUseTime = DateTime.UtcNow;
                _object.OnSpawn();
                return _object;
            }

            public void UnSpawn()
            {
                _object.OnUnSpawn();
                _object.LastUseTime = DateTime.UtcNow;
                _spawnCount--;
                if (_spawnCount < 0)
                {
                    Log.Error("object {0} spawn count < 0", Name);
                }
            }

            public void Release()
            {
                _object.Release();
            }

            public bool IsInUse
            {
                get => _spawnCount > 0;
            }
        }
    }
}
